home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / uupc11yt.zip / UTIL / GENSIG.C < prev    next >
C/C++ Source or Header  |  1993-04-10  |  22KB  |  573 lines

  1. /*--------------------------------------------------------------------*/
  2. /*       Program:    gensig.c             24 July 1991                */
  3. /*       Author:     Andrew H. Derbyshire                             */
  4. /*       Address:    ahd@kew.com                                      */
  5. /*       Function:   Append a random quote to an electronic           */
  6. /*                   mail signature file                              */
  7. /*       Language:   Borland C++ 2.0 (in ANSI C mode)                 */
  8. /*       Arguments:  Name of file with fixed text input               */
  9. /*                   Name of file with variable quotes                */
  10. /*                   Name of file to be written                       */
  11. /*--------------------------------------------------------------------*/
  12.  
  13. /*--------------------------------------------------------------------*/
  14. /*                          RCS Information                           */
  15. /*--------------------------------------------------------------------*/
  16.  
  17. /*
  18.  *    $Id: GENSIG.C 1.3 1993/04/11 00:33:54 ahd Exp $
  19.  *
  20.  *    Revision history:
  21.  *    $Log: GENSIG.C $
  22.  * Revision 1.3  1993/04/11  00:33:54  ahd
  23.  * Global edits for year, TEXT, etc.
  24.  *
  25.  * Revision 1.2  1993/03/06  23:04:54  ahd
  26.  * Alter message to include output files
  27.  *
  28.  * Revision 1.1  1992/11/15  04:29:22  ahd
  29.  * Initial revision
  30.  *
  31.  */
  32.  
  33. static char rcsid[] = "$Id: GENSIG.C 1.3 1993/04/11 00:33:54 ahd Exp $";
  34.  
  35. /*--------------------------------------------------------------------*/
  36. /*                       Standard include files                       */
  37. /*--------------------------------------------------------------------*/
  38.  
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <io.h>
  42. #include <direct.h>
  43. #include <sys/types.h>
  44. #include <sys/stat.h>
  45. #include <string.h>
  46. #include <time.h>
  47.  
  48. /*--------------------------------------------------------------------*/
  49. /*                    UUPC/extended include files                     */
  50. /*--------------------------------------------------------------------*/
  51.  
  52. #include "lib.h"
  53. #include "timestmp.h"
  54.  
  55. /*--------------------------------------------------------------------*/
  56. /*                            Local macros                            */
  57. /*--------------------------------------------------------------------*/
  58.  
  59. #define bitsper(s) (8 * (sizeof s))
  60.  
  61. #define bitflag(x, s) (1 << ((bitsper(s) - 1) - x))
  62.  
  63. #define biton( s, offset ) \
  64.                (( s[ (size_t) (offset / bitsper(*s)) ] ) & \
  65.                 bitflag(offset % bitsper( *s ), *s))
  66.  
  67. #define bitoff( s, offset) (!biton(s, offset))
  68.  
  69. /*--------------------------------------------------------------------*/
  70. /*                    Internal function prototypes                    */
  71. /*--------------------------------------------------------------------*/
  72.  
  73. static void usage( void );
  74.  
  75. static long chooseit( struct stat *current_status,
  76.        const char *lookaside,
  77.                  const char *quoteused,
  78.                  const char *fname ,
  79.                  const char *target);
  80.  
  81. static long getquote( const char *data, const char *target);
  82.  
  83. static void CopyQuote( const char *fname, long where, FILE *stream);
  84.  
  85. static void CopyFixed( const char *fname, FILE *stream );
  86.  
  87. static long chooseavailable( const char *quoteused, long quotes );
  88.  
  89. currentfile();
  90.  
  91. /*--------------------------------------------------------------------*/
  92. /*    m a i n                                                         */
  93. /*                                                                    */
  94. /*    main program                                                    */
  95. /*--------------------------------------------------------------------*/
  96.  
  97. void main( int argc, char **argv)
  98. {
  99.  
  100.    long where;
  101.    FILE *stream;
  102.  
  103.    banner( argv );
  104.  
  105. /*--------------------------------------------------------------------*/
  106. /*                  Validate the number of arguments                  */
  107. /*--------------------------------------------------------------------*/
  108.  
  109.       if ( argc !=  4 )
  110.          usage();
  111.  
  112. /*--------------------------------------------------------------------*/
  113. /*    Determine the number of the quotes available, and then          */
  114. /*    select one                                                      */
  115. /*--------------------------------------------------------------------*/
  116.  
  117.       where = getquote( argv[2], argv[3] );
  118.  
  119. /*--------------------------------------------------------------------*/
  120. /*                      Open up our output file                       */
  121. /*--------------------------------------------------------------------*/
  122.  
  123.       stream = fopen( argv[3] , "w");
  124.       if ( stream == NULL )
  125.       {
  126.          perror( argv[3] );
  127.          exit(1);
  128.       }
  129.  
  130. /*--------------------------------------------------------------------*/
  131. /*           Copy the fixed and variable parts of the file            */
  132. /*--------------------------------------------------------------------*/
  133.  
  134.       CopyFixed( argv[1], stream );
  135.       CopyQuote( argv[2], where, stream );
  136.  
  137. /*--------------------------------------------------------------------*/
  138. /*                   Close up and return to caller                    */
  139. /*--------------------------------------------------------------------*/
  140.  
  141.       fclose( stream );
  142.       exit( 0 );
  143.  
  144. } /* main */
  145.  
  146. /*--------------------------------------------------------------------*/
  147. /*    u s a g e                                                       */
  148. /*                                                                    */
  149. /*    Report program usage and then exit                              */
  150. /*--------------------------------------------------------------------*/
  151.  
  152. static void usage( void )
  153. {
  154.    printf("Usage:\tgensig\taddr-file quote-file output-file\n");
  155.    printf("\taddr-file\tFixed portion of signature file\n");
  156.    printf("\tquote-file\tFile of quotes, separated by delimiter lines\n");
  157.    printf("\toutput-file\tOutput file with fixed portion and single quote\n");
  158.    exit( 2 );
  159. } /* usage */
  160.  
  161. /*--------------------------------------------------------------------*/
  162. /*    g e t q u o t e                                                 */
  163. /*                                                                    */
  164. /*    Select a quote to process                                       */
  165. /*--------------------------------------------------------------------*/
  166.  
  167. static long getquote( const char *data, const char *target)
  168. {
  169.    struct stat current_status;
  170.    long where;
  171.  
  172.    char lookaside[FILENAME_MAX];
  173.    char quoteused[FILENAME_MAX];
  174.    char drive[FILENAME_MAX],
  175.         dir[FILENAME_MAX],
  176.         file[FILENAME_MAX],
  177.         ext[FILENAME_MAX];
  178.  
  179. /*--------------------------------------------------------------------*/
  180. /*       Get size and data information on the quotes data file        */
  181. /*--------------------------------------------------------------------*/
  182.  
  183.    if(stat((char *) data, ¤t_status ) <0)
  184.    {
  185.       perror( data );         /* If no data file, panic gracefully   */
  186.       exit( 3 );
  187.    } /* if */
  188.  
  189. /*--------------------------------------------------------------------*/
  190. /*       Build the lookaside file name from the data file name        */
  191. /*--------------------------------------------------------------------*/
  192.  
  193. #ifdef __TURBOC__
  194.    fnsplit( data, drive, dir, file, ext);
  195.    fnmerge( lookaside, drive, dir, file, ".las");
  196.    fnmerge( quoteused, drive, dir, file, ".qus");
  197. #else
  198.    _splitpath( data, drive, dir, file, ext);
  199.    _makepath( lookaside, drive, dir, file, ".las");
  200.    _makepath( quoteused, drive, dir, file, ".qus");
  201. #endif /* __TURBOC__ */
  202.  
  203. /*--------------------------------------------------------------------*/
  204. /*    Now get the location of the quote; if it fails the first        */
  205. /*    time, then the lookaside buffer is updated and we can try       */
  206. /*    again                                                           */
  207. /*--------------------------------------------------------------------*/
  208.  
  209.    where = chooseit( ¤t_status, lookaside, quoteused, data , target);
  210.    if  (where == -1 )
  211.    {
  212.       where = chooseit( ¤t_status, lookaside, quoteused, data, target );
  213.       if ( where == - 1)
  214.       {
  215.          printf("Unable to create lookaside file \"%s\"!\n",
  216.                   lookaside );
  217.          exit( 4 );
  218.       } /* if ( where == - 1) */
  219.    } /* if ( where == - 1) */
  220.  
  221. /*--------------------------------------------------------------------*/
  222. /*                          Return to caller                          */
  223. /*--------------------------------------------------------------------*/
  224.  
  225.    return where;
  226.  
  227. } /* getquote */
  228.  
  229. /*--------------------------------------------------------------------*/
  230. /*    c h o o s e i t                                                 */
  231. /*                                                                    */
  232. /*    Returns number of quotes in file                                */
  233. /*--------------------------------------------------------------------*/
  234.  
  235. static long chooseit( struct stat *current_status,
  236.                  const char *lookaside,
  237.                  const char *quoteused,
  238.                  const char *fname,
  239.                  const char *target)
  240. {
  241.    FILE *stream;
  242.    FILE *data;
  243.    long where;
  244.    long quotes = 0;
  245.    long quote;
  246.  
  247.    char buf[BUFSIZ];
  248.    char delimiter[BUFSIZ];
  249.  
  250. /*--------------------------------------------------------------------*/
  251. /*    Open up the lookaside file and determine if it is up to         */
  252. /*    date.  If so, choose an entry and return it.                    */
  253. /*--------------------------------------------------------------------*/
  254.  
  255.    stream = fopen( lookaside , "rb" );
  256.    if ( stream != NULL )
  257.    {
  258.       struct stat status;
  259.       fread( &status, sizeof status, 1, stream);
  260.       if ((status.st_size == current_status->st_size) &&
  261.           (status.st_mtime == current_status->st_mtime))
  262.       {                       /* Lookaside file up to date, use it   */
  263.          if( stat((char *) lookaside, &status ) < 0)
  264.          {
  265.             perror( lookaside );
  266.             exit( 5 );
  267.          } /* if */
  268.  
  269.          quotes = (status.st_size - sizeof status) / sizeof where;
  270.                               /* Determine number of quote pointers
  271.                                  in lookaside file from the file's
  272.                                  length                              */
  273.  
  274.          quote = chooseavailable( quoteused, quotes);
  275.  
  276.          fseek( stream, quote * sizeof where , SEEK_CUR );
  277.                               /* Step required number of quotes
  278.                                  into the file                       */
  279.          fread( &where, sizeof where, 1, stream);
  280.                               /* Read offset in data file of quote   */
  281.          printf("Chose quote %ld of %ld from %s for %s:\n\n",
  282.                   quote + 1 , quotes, fname, target);
  283.                               /* Announce number of quote of the day */
  284.          fclose( stream );    /* Done with lookaside file, of course */
  285.          return where;        /* Return position in file to caller   */
  286.       } /* if */
  287.       else
  288.          fclose( stream );
  289.    } /* if ( stream != NULL ) */
  290.    else
  291.       perror( lookaside );
  292.  
  293. /*--------------------------------------------------------------------*/
  294. /*               We have to rewrite the lookaside file                */
  295. /*--------------------------------------------------------------------*/
  296.  
  297.    unlink( quoteused );          /* Make all quotes available        */
  298.  
  299.    data   = fopen( fname, "rt");          /* Open data file to scan  */
  300.    if ( data == NULL )                    /* Did it open?            */
  301.    {
  302.       perror( fname );                    /* No --> Error            */
  303.       exit( 6 );
  304.    }
  305.  
  306.    stream = fopen( lookaside , "wb" );    /* Open lookaside file     */
  307.    if ( stream == NULL )                  /* Did it open?            */
  308.    {
  309.       perror( lookaside );                /* No --> Error            */
  310.       exit( 7 );
  311.    }
  312.  
  313. /*--------------------------------------------------------------------*/
  314. /*    Start the new lookaside file with the status of the data        */
  315. /*    file for later comparisons                                      */
  316. /*--------------------------------------------------------------------*/
  317.  
  318.    fwrite( current_status, sizeof *current_status, 1, stream);
  319.  
  320. /*--------------------------------------------------------------------*/
  321. /*    Get the first line of the file, which will contain the          */
  322. /*    delimiter line                                                  */
  323. /*--------------------------------------------------------------------*/
  324.  
  325.    fgets(delimiter, BUFSIZ, data );
  326.    where = ftell( data );  /* Get location of possible first quote   */
  327.  
  328. /*--------------------------------------------------------------------*/
  329. /*                  Now process the rest of the file                  */
  330. /*--------------------------------------------------------------------*/
  331.  
  332.    while( fgets(buf, BUFSIZ, data ) != NULL )
  333.    {
  334.       if ( strcmp( buf, delimiter ))   /* Delimiter line?            */
  335.       {                                /* No --> data line           */
  336.          if ( where != -1L )  /* First line of new quote?            */
  337.          {                    /* Yes --> Write location to lookaside */
  338.             quotes ++ ;
  339.             fwrite( &where, sizeof where, 1, stream);
  340.             where = -1L;
  341.          } /* if */
  342.       } /* if */
  343.       else
  344.          where = ftell( data );        /* Delimiter line, remember
  345.                                           location of NEXT line in
  346.                                           file                       */
  347.    } /* while */
  348.  
  349. /*--------------------------------------------------------------------*/
  350. /*                 Close up shop and return to caller                 */
  351. /*--------------------------------------------------------------------*/
  352.  
  353.    fclose( stream );
  354.    fclose( data );
  355.  
  356.    if ( quotes == 1 )
  357.    {
  358.       printf("Invalid data file; first line not a delimiter line!");
  359.       exit( 99 );
  360.    }
  361.  
  362.    printf("Updated lookaside file %s with %d quotes.\n",
  363.                lookaside , quotes);
  364.  
  365.    return -1;                 /* Inform caller that lookaside
  366.                                  file was updated                    */
  367. } /* chooseit */
  368.  
  369. /*--------------------------------------------------------------------*/
  370. /*    c h o o s e a v a i l a b l e                                   */
  371. /*                                                                    */
  372. /*    Select a quote from available list                              */
  373. /*--------------------------------------------------------------------*/
  374.  
  375. static long chooseavailable( const char *quoteused, long quotes )
  376. {
  377.    FILE *stream;
  378.    unsigned char *quotelist;
  379.  
  380.    size_t listsize = (size_t) (( quotes + bitsper(*quotelist) - 1 ) /
  381.                               bitsper(*quotelist));
  382.    long quote;
  383.    long available = quotes;
  384.    long select;
  385.  
  386. /*--------------------------------------------------------------------*/
  387. /*                 Initialize the bit array of quotes                 */
  388. /*--------------------------------------------------------------------*/
  389.  
  390.    quotelist = malloc( listsize );
  391.    checkref( quotelist );
  392.  
  393. /*--------------------------------------------------------------------*/
  394. /*             Open up the used quoted file, if possible              */
  395. /*--------------------------------------------------------------------*/
  396.  
  397.    stream = fopen( quoteused, "rb");
  398.  
  399. /*--------------------------------------------------------------------*/
  400. /*              Determine the number of available quotes              */
  401. /*--------------------------------------------------------------------*/
  402.  
  403.    if ( stream != NULL )
  404.    {
  405.  
  406.       if (fread (&available, sizeof available, 1 , stream) < 1 )
  407.       {
  408.          perror(  quoteused );
  409.          available = 0;
  410.       }
  411.       else if ( quotes <= available )
  412.          available = 0;
  413.       else if (fread (quotelist, sizeof *quotelist, listsize , stream) <
  414.                   listsize)
  415.       {
  416.          available = 0;
  417.          perror( quoteused );
  418.       }
  419.  
  420.       fclose( stream );
  421.    } /* if */
  422.    else
  423.       available = 0;
  424.  
  425.    if ( available <= ( quotes / 10 ))
  426.    {
  427.       memset( quotelist, '\0', listsize );
  428.       printf("Resetting available quotes list\n");
  429.       available = quotes;
  430.    }
  431.  
  432. /*--------------------------------------------------------------------*/
  433. /*                       Now, choose the quote                        */
  434. /*--------------------------------------------------------------------*/
  435.  
  436.    srand ( time( NULL ));     /* Initialize the generator      */
  437.    select = rand() % available ;
  438.                         /* ... Lucky seven?                    */
  439.  
  440. /*--------------------------------------------------------------------*/
  441. /*                         end debugging info                         */
  442. /*--------------------------------------------------------------------*/
  443.  
  444.    quote = 0;
  445.    while( quote < quotes )
  446.    {
  447.       if ( bitoff( quotelist, quote ))
  448.          select--;
  449.  
  450.       if ( select > 0 )
  451.          quote++;
  452.       else
  453.          break;
  454.    }
  455.  
  456.    if ( quote == quotes )           /* Did we overflow the array?    */
  457.       panic();                      /* Must have a bug!              */
  458.  
  459. /*--------------------------------------------------------------------*/
  460. /*                Now update our data and write it out                */
  461. /*--------------------------------------------------------------------*/
  462.  
  463.    stream = fopen( quoteused, "wb");
  464.    if ( stream == NULL )
  465.    {
  466.       perror( quoteused );
  467.       panic();
  468.    }
  469.  
  470.    quotelist[ (size_t) (quote / bitsper(*quotelist)) ] |=
  471.                bitflag( quote % bitsper(*quotelist), *quotelist );
  472.  
  473.    available -= 1;
  474.  
  475.    fwrite(&available, sizeof available, 1 , stream);
  476.    fwrite(quotelist,  sizeof *quotelist, listsize , stream);
  477.    fclose( stream );
  478.  
  479. /*--------------------------------------------------------------------*/
  480. /*                   Return the quote to the caller                   */
  481. /*--------------------------------------------------------------------*/
  482.  
  483.    return quote;
  484.  
  485. } /* chooseavailable */
  486.  
  487. /*--------------------------------------------------------------------*/
  488. /*    C o p y F i x e d                                               */
  489. /*                                                                    */
  490. /*    Copy fixed input text (user name and address) to output file    */
  491. /*--------------------------------------------------------------------*/
  492.  
  493. static void CopyFixed( const char *fname, FILE *stream )
  494. {
  495.    FILE *input;
  496.    char buf[BUFSIZ];
  497.  
  498. /*--------------------------------------------------------------------*/
  499. /*                    Open input file for copying                     */
  500. /*--------------------------------------------------------------------*/
  501.  
  502.    input = fopen( fname, "r");
  503.    if ( input == NULL )
  504.    {
  505.       perror( fname );
  506.       exit ( 8 );
  507.    }
  508.  
  509. /*--------------------------------------------------------------------*/
  510. /*             Copy the fixed input to the signature file             */
  511. /*--------------------------------------------------------------------*/
  512.  
  513.    while( fgets( buf, BUFSIZ, input ) != NULL)
  514.       fputs( buf, stream );
  515.  
  516. /*--------------------------------------------------------------------*/
  517. /*                 Close up shop and return to caller                 */
  518. /*--------------------------------------------------------------------*/
  519.  
  520.    fclose( input );
  521.  
  522. } /* CopyFixed */
  523.  
  524. /*--------------------------------------------------------------------*/
  525. /*    C o p y Q u o t e                                               */
  526. /*                                                                    */
  527. /*    Write a quote to the output file                                */
  528. /*--------------------------------------------------------------------*/
  529.  
  530. static void CopyQuote( const char *fname, long where, FILE *stream)
  531. {
  532.    FILE *input;
  533.    char buf[BUFSIZ];
  534.    char delimiter[BUFSIZ];
  535.  
  536. /*--------------------------------------------------------------------*/
  537. /*         Open up the quotes file and get the delimiter line         */
  538. /*--------------------------------------------------------------------*/
  539.  
  540.    input = fopen( fname, "r");
  541.    if ( input == NULL )
  542.    {
  543.       perror( fname );
  544.       exit ( 9 );
  545.    }
  546.  
  547.    fgets(delimiter, BUFSIZ, input );
  548.  
  549. /*--------------------------------------------------------------------*/
  550. /*   Position to the beginning of the actual quote to be processed    */
  551. /*--------------------------------------------------------------------*/
  552.  
  553.    fseek( input, where , SEEK_SET );
  554.  
  555. /*--------------------------------------------------------------------*/
  556. /*      Copy the quote to both the signature file and the screen      */
  557. /*--------------------------------------------------------------------*/
  558.  
  559.    while( fgets( buf, BUFSIZ, input ) != NULL)
  560.    {
  561.       if (!strcmp( delimiter, buf ))   /* Delimiter line?            */
  562.          break;                        /* Yes --> End of quote       */
  563.       fputs( buf, stream );   /* Copy quote to signature file        */
  564.       fputs( buf, stdout );   /* Copy quote to screen                */
  565.    } /* while( fgets( buf, BUFSIZ, input ) != NULL) */
  566.  
  567. /*--------------------------------------------------------------------*/
  568. /*                 Close up shop and return to caller                 */
  569. /*--------------------------------------------------------------------*/
  570.  
  571.    fclose( input );
  572. } /* CopyQuote */
  573.